﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WindowsFormsApp1.Utils;

namespace Communication
{
    internal class MessageGenerationModule
    {
        private static byte PIID = 0;
        public MessageGenerationModule() { }
        public enum RequestMode
        {
            Read = 0x05,
            SET = 0x06,
            ACTION = 0x07,
            REPORT = 0x08,
            PROXY = 0x09,

        }
        public enum ReadMode
        {
            GetRequestNormal = 0x01,
            GetRequestNormalList = 0x02,
            GetRequestRecord = 0x03,
            GetRequestRecordList = 0x04,
            GetRequestNext = 0x05,
            GetRequestMD5 = 0x06,
        }
        public enum SetMode
        {
            SetRequestNormal = 0x01,
            SetRequestNormalList = 0x02,
            SetThenGetRequestNormalList = 0x03,
        }
        public enum ActionMode
        {
            ActionRequest = 0x01,
            ActionRequestList = 0x02,
            ActionThenGetRequestNormalList = 0x03,
        }

        public enum ReportMode
        {
            ReportNotificationList = 0x01,
            ReportNotificationRecordList = 0x02,
            ReportNotificationTransData = 0x03,
        }
        public enum ProxyMode
        {
            ProxyGetRequestList = 0x01,
            ProxyGetRequestRecord = 0x02,
            ProxySetRequestList = 0x03,
            ProxySetThenGetRequestList = 0x04,
            ProxyActionRequestList = 0x05,
            ProxyActionThenGetRequestList = 0x06,
            ProxyTransCommandRequest = 0x07,
        }
        public enum ResponseMode
        {
            Read = 0x85,
            SET = 0x86,
            ACTION = 0x87,
            REPORT = 0x88,
            PROXY = 0x89,
        }
        public static byte GetPIID()
        {
            if (PIID > 63)
            {
                PIID = 0;
            }
            return PIID++;
        }
        /// <summary>
        /// 生成读取报文
        /// </summary>
        /// <param name="address">设备地址</param>
        /// <param name="readMode">读取请求类型</param>
        /// <param name="OAD">对象属性描述符</param>
        /// <returns></returns>
        public static byte[] MessageGeneration(string address, ReadMode mode, string OAD, bool isDateTimeFlag)
        {
            return GetReadMessage(address, mode, OAD, isDateTimeFlag);  
        }

        public static byte[] MessageGeneration(string address, SetMode mode, Dictionary<string, string> map, bool isDateTimeFlag)
        {
            return GetSetMessage(address, mode, map, isDateTimeFlag);
        }

        private static byte[] GetReadMessage(string address, ReadMode mode, string OAD,bool isDateTimeFlag)
        {
            byte[] byteAddress = StringUtils.strToHexByte(address);
            List<byte> APDU = GetReadAPDU(mode, OAD, isDateTimeFlag);
            //定义临时字节列表
            List<byte> temp = new List<byte>();
            temp.Add(0x68);
            //长度域
            short length = (short)(2 + 1 + 1 + (short)byteAddress.Length + 1+2+(short)APDU.Count+2);
            byte[] byteLength = BitConverter.GetBytes(length);
            
            temp.AddRange(byteLength);

            //控制域
            byte control = 0x43;
            temp.Add(control);

            //地址域
            //服务器地址SA
            
            temp.Add((byte)(byteAddress.Length-1));
            Array.Reverse(byteAddress);
            temp.AddRange(byteAddress);
            //客户机地址CA
            byte ca = 0x11;
            temp.Add(ca);

            //帧头校验HCS
            temp.AddRange(CheckSum.CRC16(temp, 1));

            //链路用户数据
            temp.AddRange(APDU);

            //帧校验FCS
            temp.AddRange(CheckSum.CRC16(temp,1));

            //结束字符
            temp.Add(0x16);
            return temp.ToArray();
        }


        private static List<byte> GetReadAPDU(ReadMode mode, string OAD, bool isDateTimeFlag)
        {
            //定义临时字节列表
            List<byte> temp = new List<byte>();
            temp.Add(0x05);
            temp.Add((byte)mode);
            //PIID
            temp.Add(GetPIID());
            //应用层服务
            
            switch (mode)
            {
                case ReadMode.GetRequestNormal:
                    temp.AddRange(StringUtils.strToHexByte(OAD));
                    break;
                case ReadMode.GetRequestNormalList:
                    temp.Add((byte)(StringUtils.strToHexByte(OAD).Length / 4));
                    temp.AddRange(StringUtils.strToHexByte(OAD));
                    break;
                case ReadMode.GetRequestRecord:
                    break;
                case ReadMode.GetRequestRecordList: 
                    break;
                case ReadMode.GetRequestNext:
                    break;
                case ReadMode.GetRequestMD5:
                    break;
                default:
                    break;
            }
            //时间标签
            if (!isDateTimeFlag)
            {
                temp.Add(0);
            }
            return temp;
        }

        private static byte[] GetSetMessage(string address, SetMode mode, Dictionary<string, string> map, bool isDateTimeFlag)
        {
            byte[] byteAddress = StringUtils.strToHexByte(address);
            List<byte> APDU = GetSetAPDU(mode, map, isDateTimeFlag);
            //定义临时字节列表
            List<byte> temp = new List<byte>();
            temp.Add(0x68);
            //长度域
            short length = (short)(2 + 1 + 1 + (short)byteAddress.Length + 1 + 2 + (short)APDU.Count + 2);
            byte[] byteLength = BitConverter.GetBytes(length);

            temp.AddRange(byteLength);

            //控制域
            byte control = 0x43;
            temp.Add(control);

            //地址域
            //服务器地址SA

            temp.Add((byte)(byteAddress.Length - 1));
            Array.Reverse(byteAddress);
            temp.AddRange(byteAddress);
            //客户机地址CA
            byte ca = 0x11;
            temp.Add(ca);

            //帧头校验HCS
            temp.AddRange(CheckSum.CRC16(temp, 1));

            //链路用户数据
            temp.AddRange(APDU);

            //帧校验FCS
            temp.AddRange(CheckSum.CRC16(temp, 1));

            //结束字符
            temp.Add(0x16);
            return temp.ToArray();
        }
        private static List<byte> GetSetAPDU(SetMode mode, Dictionary<string,string> map, bool isDateTimeFlag)
        {
            //定义临时字节列表
            List<byte> temp = new List<byte>();
            temp.Add(0x06);
            temp.Add((byte)mode);
            //PIID
            temp.Add(GetPIID());
            //应用层服务

            switch (mode)
            {
                case SetMode.SetRequestNormal:
                    temp.AddRange(StringUtils.strToHexByte(map.Keys.First()));//OAD
                    temp.AddRange(StringUtils.strToHexByte(map[map.Keys.First()]));//Value
                    break;
                case SetMode.SetRequestNormalList:
                    temp.Add((byte)map.Keys.Count());
                    foreach (var item in map)
                    {
                        temp.AddRange(StringUtils.strToHexByte(item.Key));
                        temp.AddRange(StringUtils.strToHexByte(item.Value));
                    }
                    
                    break;
                case SetMode.SetThenGetRequestNormalList:
                    break;
                default:
                    break;
            }
            //时间标签
            if (!isDateTimeFlag)
            {
                temp.Add(0);
            }
            return temp;
        }
    }
}
